
#ifndef __LINUX
  #include "StdAfx.h"
#endif


#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#include "OTClient.h"
#include "Python.h"

#ifdef __LINUX
  #include <unistd.h>
  #define Sleep(x) usleep((x * 1000))
  //typedef LPCTSTR   char*
#endif



//#include "opentick.h"


/*
global OTClient


python functions:
  addHost
  login
  logout
  isLoggedIn
  getStatus

  register callback

  onLogin
  onRestoreConnection
  onStatisChanged
  onError
  onMessage
  onListExchanges
  onListSymbols
  onRealtimeQuote
  onRealtimeMMQuote
  onRealtimeTrade
  onRealtimeBBO
  onTodaysOHL
  onEquityInit
  onBookCancel
  onBookChange
  onBookDelete
  onBookExecute
  onBookOrder
  onBookPriceLevel
  onBookPurge
  onBookReplace

  onHistQuote
  onHistMMQuote
  onHistTrade
  onHistBBO
  onHistOHLC
  onSplit
  onDividend
  onOptionInit

  onHistBookCancel
  onHistBookChange
  onHistBookDelete
  onHistBookExecute
  onHistBookOrder
  onHistBookPriceLevel
  onHistBookPurge
  onHistBookReplace

  requestTickStream
  requestBookStream
  requestMarketDepth
  requestOptionChain
  requestEquityInit
  requestHistData
  requestHistTicks
  requestTodaysOHL
  requestListExchanges
  requestListSymbols
  requestSplits
  requestDiviends
  requestTickSnapshot
  requestOptionChainSnapshot
  requestOptionInit
  requestHistBooks
  cancelTickStream
  cancelBookStream
  cancelMarketDepth
  cancelHistData
  cancelOptionChain
constants


  */

//a structure for storing the python thread state when getting the global interpreter lock


/******** our special OTClient that feeds messages into a python callback ********/
class TestClient : public OTClient  { 
  public:
	int debug;
	PyObject *callback;

    TestClient () {
		debug=0;
    }

    virtual ~TestClient ()  {
    }
  
    virtual void onLogin () {
		if (debug) printf("onLogin\n");
		PyGILState_STATE state = PyGILState_Ensure();
	    PyObject *args = Py_BuildValue("({ss})", "ottype", "onLogin");
		PyObject *result = PyEval_CallObject(callback, args);
		Py_DECREF(args);
		if(result) Py_DECREF(result);
		PyGILState_Release(state);
	}

    virtual void onRestoreConnection () {
		PyGILState_STATE state = PyGILState_Ensure();
	    PyObject *args = Py_BuildValue("({ss})", "ottype", "onRestoreConnection");
		PyObject *result = PyEval_CallObject(callback, args);
		Py_DECREF(args);
		if(result) Py_DECREF(result);
		PyGILState_Release(state);
	}

    virtual void onStatusChanged(int status) {
		PyGILState_STATE state = PyGILState_Ensure();
	    PyObject *args = Py_BuildValue("({ss,si})",
			"ottype", "onStatusChanged",
			"status", status);
		PyObject *result = PyEval_CallObject(callback, args);
		Py_DECREF(args);
		if(result) Py_DECREF(result);
		PyGILState_Release(state);
	}

    virtual void onError (OTError * error) {
		PyGILState_STATE state = PyGILState_Ensure();
	    PyObject *args = Py_BuildValue("({ss,si,si,si,ss})", 
			"ottype", "onError",
			"requestId", error->getRequestId(),
			"type", error->getType(),
			"code", error->getCode(),
			"description", error->getDescription());
		PyObject *result = PyEval_CallObject(callback, args);
		Py_DECREF(args);
		if(result) Py_DECREF(result);
		PyGILState_Release(state);
    }

	virtual void onMessage (OTMessage *message)  {
		PyGILState_STATE state = PyGILState_Ensure();
	    PyObject *args = Py_BuildValue("({ss,si,si,ss})", 
			"ottype", "onMessage",
			"requestId", message->getRequestId(),
			"code", message->getCode(),
			"description", message->getDescription());
		PyObject *result = PyEval_CallObject(callback, args);
		Py_DECREF(args);
		if(result) Py_DECREF(result);
		PyGILState_Release(state);
    }

    virtual void onListExchanges (OTExchange * listExchange, int exchangeNum) {
		int	num;
		LPCTSTR str;

		PyGILState_STATE state = PyGILState_Ensure();
		PyObject *exchanges = Py_BuildValue("[]");
        for (int i = 0; i < exchangeNum; i++)  {
			if (i==0) {
				num=listExchange[i].getRequestId();
				str=listExchange[i].getSubscriptionURL();
			}
			PyObject *exchange = Py_BuildValue("{si,ss,ss,ss}", 
				"available", listExchange[i].getAvailable(),
				"code", listExchange[i].getCode(),
				"title", listExchange[i].getTitle(),
				"description", listExchange[i].getDescription()
				);
			PyList_Append(exchanges, exchange);
			Py_DECREF(exchange);
		}

		PyObject *args = Py_BuildValue("({ss,si,ss,sO})", 
				"ottype", "onListExchanges",
				"requestId", num,
				"subscriptionURL", (char *)str,
				"exchanges", exchanges
				);
		Py_DECREF(exchanges);
		PyObject *result = PyEval_CallObject(callback, args);
		Py_DECREF(args);
		if(result) Py_DECREF(result);

		PyGILState_Release(state);
    }

	virtual void onListSymbols (OTSymbol *symbols, int symbolCount) {
		int	num=0;

		PyGILState_STATE state = PyGILState_Ensure();
		PyObject *symbollist = Py_BuildValue("[]");
        for (int i = 0; i < symbolCount; i++)  {
			if (i==0) {
				num=symbols[i].getRequestId();
			}
			PyObject *symbol = Py_BuildValue("{ss,ss,ss,si}", 
				"code", symbols[i].getCode(),
				"company", symbols[i].getCompany(),
				"currency", symbols[i].getCurrency(),
				"type", symbols[i].getType()
				);
			PyList_Append(symbollist, symbol);
			Py_DECREF(symbol);
		}

		PyObject *args = Py_BuildValue("({ss,si,sO})", 
				"ottype", "onListSymbols",
				"requestId", num,
				"symbols", symbollist
				);
		Py_DECREF(symbollist);
		PyObject *result;
		result = PyEval_CallObject(callback, args);
		Py_DECREF(args);
		if(result) Py_DECREF(result);

		PyGILState_Release(state);
    }


    virtual void onRealtimeQuote (OTQuote *quote)  {
		if (debug) printf("onRealtimeQuote, %d\n", quote->getRequestId());
		PyGILState_STATE state = PyGILState_Ensure();
	    PyObject *args = Py_BuildValue("({ss,si,si, sd,si,sd,si, ss,ss,sc,sc,ss})", 
			"ottype", "onRealtimeQuote",
			"requestId", quote->getRequestId(),
			"timestamp", quote->getTimestamp(),
			"askPrice", quote->getAskPrice(),
			"askSize", quote->getAskSize(),
			"bidPrice", quote->getBidPrice(),
			"bidSize", quote->getBidSize(),
			"bidExchange", quote->getBidExchange(),
			"askExchange", quote->getAskExchange(),
			"indicator", quote->getIndicator(),
			"tickIndicator", quote->getTickIndicator(),
			"symbol", quote->getSymbol()
			);
			PyObject *result = PyEval_CallObject(callback, args);
		Py_DECREF(args);
		if(result) Py_DECREF(result);
		PyGILState_Release(state);
    }


    virtual void onRealtimeMMQuote (OTMMQuote *mmQuote)  {
		if (debug) printf("onRealtimeMMQuote, %d\n", mmQuote->getRequestId());
		PyGILState_STATE state = PyGILState_Ensure();
	    PyObject *args = Py_BuildValue("({ss,si,si, sd,si,sd,si, ss,sc,ss})", 
			"ottype", "onRealtimeMMQuote",
			"requestId", mmQuote->getRequestId(),
			"timestamp", mmQuote->getTimestamp(),
			"askPrice", mmQuote->getAskPrice(),
			"askSize", mmQuote->getAskSize(),
			"bidPrice", mmQuote->getBidPrice(),
			"bidSize", mmQuote->getBidSize(),
			"MMID", mmQuote->getMMID(),
			"indicator", mmQuote->getIndicator(),
			"symbol", mmQuote->getSymbol()
			);
			PyObject *result = PyEval_CallObject(callback, args);
		Py_DECREF(args);
		if(result) Py_DECREF(result);
		PyGILState_Release(state);
    }


    virtual void onRealtimeTrade(OTTrade *trade)  {
		if (debug) printf("onRealtimeTrade, %d\n", trade->getRequestId());
		PyGILState_STATE state = PyGILState_Ensure();
	    PyObject *args = Py_BuildValue("({ss,si,si, sd,si,sl,si,sc,sc, si,si,si,si,si,si,si,si, ss})", 
			"ottype", "onRealtimeTrade",
			"requestId", trade->getRequestId(),
			"timestamp", trade->getTimestamp(),

			"price", trade->getPrice(),
			"size", trade->getSize(),
			"volume", (long)trade->getVolume(),
			"sequenceNumber", trade->getSequenceNumber(),
			"indicator", trade->getIndicator(),
			"tickIndicator", trade->getTickIndicator(),

			"isOpen", (int) trade->isOpen(),
			"isHigh", (int) trade->isHigh(),
			"isLow", (int) trade->isLow(),
			"isClose", (int) trade->isClose(),
			"isUpdateLast", (int) trade->isUpdateLast(),
			"isUpdateVolume", (int) trade->isUpdateVolume(),
			"isCancel", (int) trade->isCancel(),
			"isFromBook", (int) trade->isFromBook(),
			"symbol", trade->getSymbol()
			);
		PyObject *result = PyEval_CallObject(callback, args);
		Py_DECREF(args);
		if(result) Py_DECREF(result);
		PyGILState_Release(state);
    }

	virtual void onRealtimeBBO (OTBBO *bbo) {
		PyGILState_STATE state = PyGILState_Ensure();
	    PyObject *args = Py_BuildValue("({ss,si,si,sd,si,sc,ss})", 
			"ottype", "onRealtimeBBO",
			"requestId", bbo->getRequestId(),
			"timestamp", bbo->getTimestamp(),
			"price", bbo->getPrice(),
			"size", bbo->getSize(),
			"side", bbo->getSide(),
			"symbol", bbo->getSymbol()
			);
			PyObject *result = PyEval_CallObject(callback, args);
		Py_DECREF(args);
		if(result) Py_DECREF(result);
		PyGILState_Release(state);		
	}

	virtual void onTodaysOHL (int requestId, double openPrice, double highPrice, double lowPrice) {
		PyGILState_STATE state = PyGILState_Ensure();
	    PyObject *args = Py_BuildValue("({ss,si,sd,sd,sd})", 
			"ottype", "onTodaysOHL",
			"requestId", requestId,
			"openPrice", openPrice,
			"highPrice", openPrice,
			"lowPrice", openPrice
			);
			PyObject *result = PyEval_CallObject(callback, args);
		Py_DECREF(args);
		if(result) Py_DECREF(result);
		PyGILState_Release(state);
	}



	virtual void onEquityInit (OTEquityInit *equityInit)  {
		PyGILState_STATE state = PyGILState_Ensure();
	    PyObject *args = Py_BuildValue("({ss,si,si,si,si,si,ss,ss,ss,ss,ss,ss,ss,ss,sd,sd,sd,sd,sl,sl})", 
			"ottype", "onEquityInit",
			"requestId", equityInit->getRequestId(),
			"instrumentType", equityInit->getInstrumentType(),
			"isUPC11830", (int)equityInit->isUPC11830(),
			"isSmallCap", (int)equityInit->isSmallCap(),
			"isTestIssue", (int)equityInit->isTestlssue(),
			"currency", equityInit->getCurrency(),
			"companyName", equityInit->getCompanyName(),
			"prevCloseDate", equityInit->getPrevCloseDate(),
			"annualHighDate", equityInit->getAnnualHighDate(),
			"annualLowDate", equityInit->getAnnualLowDate(),
			"earningsDate", equityInit->getEarningsDate(),
			"CUSIP", equityInit->getCUSIP(),
			"ISIN", equityInit->getISIN(),
			"prevClosePrice", equityInit->getPrevClosePrice(),
			"annualHighPrice", equityInit->getAnnualHighPrice(),
			"annualLowPrice", equityInit->getAnnualLowPrice(),
			"earningsPrice", equityInit->getEarningsPrice(),
			"totalShares", (long) equityInit->getTotalShares(),
			"averageVolume", (long) equityInit->getAverageVolume()
			);
			PyObject *result = PyEval_CallObject(callback, args);
		Py_DECREF(args);
		if(result) Py_DECREF(result);
		PyGILState_Release(state);
	}


	virtual void onBookCancel (OTBookCancel *bookCancel) {
		PyGILState_STATE state = PyGILState_Ensure();
	    PyObject *args = Py_BuildValue("({ss,si,si,ss,si})", 
			"ottype", "onBookCancel",
			"requestId", bookCancel->getRequestId(),
			"timestamp", bookCancel->getTimestamp(),
			"orderRef", bookCancel->getOrderRef(),
			"size", bookCancel->getSize()
			);
			PyObject *result = PyEval_CallObject(callback, args);
		Py_DECREF(args);
		if(result) Py_DECREF(result);
		PyGILState_Release(state);		
	}


	virtual void onBookChange (OTBookChange *bookChange)  {
		PyGILState_STATE state = PyGILState_Ensure();
	    PyObject *args = Py_BuildValue("({ss,si,si,ss,si,sd})", 
			"ottype", "onBookChange",
			"requestId", bookChange->getRequestId(),
			"timestamp", bookChange->getTimestamp(),
			"orderRef", bookChange->getOrderRef(),
			"size", bookChange->getSize(),
			"price", bookChange->getPrice()
			);
			PyObject *result = PyEval_CallObject(callback, args);
		Py_DECREF(args);
		if(result) Py_DECREF(result);
		PyGILState_Release(state);		
	}


	virtual void onBookDelete (OTBookDelete *bookDelete)  {
		PyGILState_STATE state = PyGILState_Ensure();
	    PyObject *args = Py_BuildValue("({ss,si,si,ss,sc,sc})", 
			"ottype", "onBookDelete",
			"requestId", bookDelete->getRequestId(),
			"timestamp", bookDelete->getTimestamp(),
			"orderRef", bookDelete->getOrderRef(),
			"side", bookDelete->getSide(),
			"deleteType", bookDelete->getDeleteType()
			);
			PyObject *result = PyEval_CallObject(callback, args);
		Py_DECREF(args);
		if(result) Py_DECREF(result);
		PyGILState_Release(state);		
	}


	virtual void onBookExecute (OTBookExecute *bookExecute)  {
		PyGILState_STATE state = PyGILState_Ensure();
	    PyObject *args = Py_BuildValue("({ss,si,si,ss,si,si})", 
			"ottype", "onBookExecute",
			"requestId", bookExecute->getRequestId(),
			"timestamp", bookExecute->getTimestamp(),
			"orderRef", bookExecute->getOrderRef(),
			"size", bookExecute->getSize(),
			"matchNumber", bookExecute->getMatchNumber()
			);
			PyObject *result = PyEval_CallObject(callback, args);
		Py_DECREF(args);
		if(result) Py_DECREF(result);
		PyGILState_Release(state);		
	}

	virtual void onBookOrder (OTBookOrder *bookOrder)  {
		PyGILState_STATE state = PyGILState_Ensure();
	    PyObject *args = Py_BuildValue("({ss,si,si,ss,si,sd,sc,si})", 
			"ottype", "onBookOrder",
			"requestId", bookOrder->getRequestId(),
			"timestamp", bookOrder->getTimestamp(),
			"orderRef", bookOrder->getOrderRef(),
			"size", bookOrder->getSize(),
			"price", bookOrder->getPrice(),
			"side", bookOrder->getSide(),
			"display", bookOrder->getDisplay()
			);
			PyObject *result = PyEval_CallObject(callback, args);
		Py_DECREF(args);
		if(result) Py_DECREF(result);
		PyGILState_Release(state);		
	}

	virtual void onBookPriceLevel (OTBookPriceLevel *bookPriceLevel)  {
		PyGILState_STATE state = PyGILState_Ensure();
	    PyObject *args = Py_BuildValue("({ss,si,si,si,sd,sc,ss})", 
			"ottype", "onBookPriceLevel",
			"requestId", bookPriceLevel->getRequestId(),
			"timestamp", bookPriceLevel->getTimestamp(),
			"size", bookPriceLevel->getSize(),
			"price", bookPriceLevel->getPrice(),
			"side", bookPriceLevel->getSide(),
			"levelId", bookPriceLevel->getLevelId()
			);
			PyObject *result = PyEval_CallObject(callback, args);
		Py_DECREF(args);
		if(result) Py_DECREF(result);
		PyGILState_Release(state);		
	}

	virtual void onBookPurge (OTBookPurge *bookPurge) {
		PyGILState_STATE state = PyGILState_Ensure();
	    PyObject *args = Py_BuildValue("({ss,si,si,ss})", 
			"ottype", "onBookPurge",
			"requestId", bookPurge->getRequestId(),
			"timestamp", bookPurge->getTimestamp(),
			"exchangeNameRoot", bookPurge->getExchangeNameRoot()
			);
			PyObject *result = PyEval_CallObject(callback, args);
		Py_DECREF(args);
		if(result) Py_DECREF(result);
		PyGILState_Release(state);		
	}

	virtual void onBookReplace (OTBookReplace *bookReplace) {
		PyGILState_STATE state = PyGILState_Ensure();
	    PyObject *args = Py_BuildValue("({ss,si,si,ss,si,sd,sc})", 
			"ottype", "onBookReplace",
			"requestId", bookReplace->getRequestId(),
			"timestamp", bookReplace->getTimestamp(),
			"orderRef", bookReplace->getOrderRef(),
			"size", bookReplace->getSize(),
			"price", bookReplace->getPrice(),
			"side", bookReplace->getSide()
			);
			PyObject *result = PyEval_CallObject(callback, args);
		Py_DECREF(args);
		if(result) Py_DECREF(result);
		PyGILState_Release(state);		
	}

	virtual void onHistBookCancel (OTBookCancel *bookCancel) {
		PyGILState_STATE state = PyGILState_Ensure();
	    PyObject *args = Py_BuildValue("({ss,si,si,ss,si})", 
			"ottype", "onBookCancel",
			"requestId", bookCancel->getRequestId(),
			"timestamp", bookCancel->getTimestamp(),
			"orderRef", bookCancel->getOrderRef(),
			"size", bookCancel->getSize()
			);
			PyObject *result = PyEval_CallObject(callback, args);
		Py_DECREF(args);
		if(result) Py_DECREF(result);
		PyGILState_Release(state);		
	}


	virtual void onHistBookChange (OTBookChange *bookChange)  {
		PyGILState_STATE state = PyGILState_Ensure();
	    PyObject *args = Py_BuildValue("({ss,si,si,ss,si,sd})", 
			"ottype", "onBookChange",
			"requestId", bookChange->getRequestId(),
			"timestamp", bookChange->getTimestamp(),
			"orderRef", bookChange->getOrderRef(),
			"size", bookChange->getSize(),
			"price", bookChange->getPrice()
			);
			PyObject *result = PyEval_CallObject(callback, args);
		Py_DECREF(args);
		if(result) Py_DECREF(result);
		PyGILState_Release(state);		
	}


	virtual void onHistBookDelete (OTBookDelete *bookDelete)  {
		PyGILState_STATE state = PyGILState_Ensure();
	    PyObject *args = Py_BuildValue("({ss,si,si,ss,sc,sc})", 
			"ottype", "onBookDelete",
			"requestId", bookDelete->getRequestId(),
			"timestamp", bookDelete->getTimestamp(),
			"orderRef", bookDelete->getOrderRef(),
			"side", bookDelete->getSide(),
			"deleteType", bookDelete->getDeleteType()
			);
			PyObject *result = PyEval_CallObject(callback, args);
		Py_DECREF(args);
		if(result) Py_DECREF(result);
		PyGILState_Release(state);		
	}


	virtual void onHistBookExecute (OTBookExecute *bookExecute)  {
		PyGILState_STATE state = PyGILState_Ensure();
	    PyObject *args = Py_BuildValue("({ss,si,si,ss,si,si})", 
			"ottype", "onBookExecute",
			"requestId", bookExecute->getRequestId(),
			"timestamp", bookExecute->getTimestamp(),
			"orderRef", bookExecute->getOrderRef(),
			"size", bookExecute->getSize(),
			"matchNumber", bookExecute->getMatchNumber()
			);
			PyObject *result = PyEval_CallObject(callback, args);
		Py_DECREF(args);
		if(result) Py_DECREF(result);
		PyGILState_Release(state);		
	}

	virtual void onHistBookOrder (OTBookOrder *bookOrder)  {
		PyGILState_STATE state = PyGILState_Ensure();
	    PyObject *args = Py_BuildValue("({ss,si,si,ss,si,sd,sc,si})", 
			"ottype", "onBookOrder",
			"requestId", bookOrder->getRequestId(),
			"timestamp", bookOrder->getTimestamp(),
			"orderRef", bookOrder->getOrderRef(),
			"size", bookOrder->getSize(),
			"price", bookOrder->getPrice(),
			"side", bookOrder->getSide(),
			"display", bookOrder->getDisplay()
			);
			PyObject *result = PyEval_CallObject(callback, args);
		Py_DECREF(args);
		if(result) Py_DECREF(result);
		PyGILState_Release(state);		
	}

	virtual void onHistBookPriceLevel (OTBookPriceLevel *bookPriceLevel)  {
		PyGILState_STATE state = PyGILState_Ensure();
	    PyObject *args = Py_BuildValue("({ss,si,si,si,sd,sc,ss})", 
			"ottype", "onBookPriceLevel",
			"requestId", bookPriceLevel->getRequestId(),
			"timestamp", bookPriceLevel->getTimestamp(),
			"size", bookPriceLevel->getSize(),
			"price", bookPriceLevel->getPrice(),
			"side", bookPriceLevel->getSide(),
			"levelId", bookPriceLevel->getLevelId()
			);
			PyObject *result = PyEval_CallObject(callback, args);
		Py_DECREF(args);
		if(result) Py_DECREF(result);
		PyGILState_Release(state);		
	}

	virtual void onHistBookPurge (OTBookPurge *bookPurge) {
		PyGILState_STATE state = PyGILState_Ensure();
	    PyObject *args = Py_BuildValue("({ss,si,si,ss})", 
			"ottype", "onBookPurge",
			"requestId", bookPurge->getRequestId(),
			"timestamp", bookPurge->getTimestamp(),
			"exchangeNameRoot", bookPurge->getExchangeNameRoot()
			);
			PyObject *result = PyEval_CallObject(callback, args);
		Py_DECREF(args);
		if(result) Py_DECREF(result);
		PyGILState_Release(state);		
	}

	virtual void onHistBookReplace (OTBookReplace *bookReplace) {
		PyGILState_STATE state = PyGILState_Ensure();
	    PyObject *args = Py_BuildValue("({ss,si,si,ss,si,sd,sc})", 
			"ottype", "onBookReplace",
			"requestId", bookReplace->getRequestId(),
			"timestamp", bookReplace->getTimestamp(),
			"orderRef", bookReplace->getOrderRef(),
			"size", bookReplace->getSize(),
			"price", bookReplace->getPrice(),
			"side", bookReplace->getSide()
			);
			PyObject *result = PyEval_CallObject(callback, args);
		Py_DECREF(args);
		if(result) Py_DECREF(result);
		PyGILState_Release(state);		
	}

	virtual void onHistQuote (OTQuote *quote)  {
		PyGILState_STATE state = PyGILState_Ensure();
	    PyObject *args = Py_BuildValue("({ss,si,si, sd,si,sd,si, ss,ss,sc,sc,ss})", 
			"ottype", "onHistQuote",
			"requestId", quote->getRequestId(),
			"timestamp", quote->getTimestamp(),
			"askPrice", quote->getAskPrice(),
			"askSize", quote->getAskSize(),
			"bidPrice", quote->getBidPrice(),
			"bidSize", quote->getBidSize(),
			"askExchange", quote->getAskExchange(),
			"bidExchange", quote->getBidExchange(),
			"indicator", quote->getIndicator(),
			"tickIndicator", quote->getTickIndicator(),
			"symbol", quote->getSymbol()
			);
			PyObject *result = PyEval_CallObject(callback, args);
		Py_DECREF(args);
		if(result) Py_DECREF(result);
		PyGILState_Release(state);
    }


    virtual void onHistMMQuote (OTMMQuote *mmQuote)  {
		PyGILState_STATE state = PyGILState_Ensure();
	    PyObject *args = Py_BuildValue("({ss,si,si, sd,si,sd,si, ss,sc,ss})", 
			"ottype", "onHistMMQuote",
			"requestId", mmQuote->getRequestId(),
			"timestamp", mmQuote->getTimestamp(),
			"askPrice", mmQuote->getAskPrice(),
			"askSize", mmQuote->getAskSize(),
			"bidPrice", mmQuote->getBidPrice(),
			"bidSize", mmQuote->getBidSize(),
			"MMID", mmQuote->getMMID(),
			"indicator", mmQuote->getIndicator(),
			"symbol", mmQuote->getSymbol()
			);
			PyObject *result = PyEval_CallObject(callback, args);
		Py_DECREF(args);
		if(result) Py_DECREF(result);
		PyGILState_Release(state);
    }

    virtual void onHistTrade(OTTrade *trade)  {
		PyGILState_STATE state = PyGILState_Ensure();
	    PyObject *args = Py_BuildValue("({ss,si,si, sd,si,sl,si,sc,sc, si,si,si,si,si,si,si,si, ss})", 
			"ottype", "onHistTrade",
			"requestId", trade->getRequestId(),
			"timestamp", trade->getTimestamp(),
			"price", trade->getPrice(),
			"size", trade->getSize(),
			"volume", (long)trade->getVolume(),
			"sequenceNumber", trade->getSequenceNumber(),
			"indicator", trade->getIndicator(),
			"tickIndicator", trade->getTickIndicator(),
			"isOpen", (int) trade->isOpen(),
			"isHigh", (int) trade->isHigh(),
			"isLow", (int) trade->isLow(),
			"isClose", (int) trade->isClose(),
			"isUpdateLast", (int) trade->isUpdateLast(),
			"isUpdateVolume", (int) trade->isUpdateVolume(),
			"isCancel", (int) trade->isCancel(),
			"isFromBook", (int) trade->isFromBook(),
			"symbol", trade->getSymbol()
			);
			PyObject *result = PyEval_CallObject(callback, args);
		Py_DECREF(args);
		if(result) Py_DECREF(result);
		PyGILState_Release(state);
    }

	virtual void onHistBBO (OTBBO *bbo) {
		PyGILState_STATE state = PyGILState_Ensure();
	    PyObject *args = Py_BuildValue("({ss,si,si,sd,si,sc,ss})", 
			"ottype", "onHistBBO",
			"requestId", bbo->getRequestId(),
			"timestamp", bbo->getTimestamp(),
			"price", bbo->getPrice(),
			"size", bbo->getSize(),
			"side", bbo->getSide(),
			"symbol", bbo->getSymbol()
			);
			PyObject *result = PyEval_CallObject(callback, args);
		Py_DECREF(args);
		if(result) Py_DECREF(result);
		PyGILState_Release(state);		
	}


    virtual void onHistOHLC (OTOHLC *data)  {
		PyGILState_STATE state = PyGILState_Ensure();
	    PyObject *args = Py_BuildValue("({ss,si,si,sd,sd,sd,sd,sl})", 
			"ottype", "onHistOHLC",
			"requestId", data->getRequestId(),
			"timestamp", data->getTimestamp(),
			"openPrice", data->getOpenPrice(),
			"highPrice", data->getHighPrice(),
			"lowPrice", data->getLowPrice(),
			"closePrice", data->getClosePrice(),
			"volume", data->getVolume()
			);
		PyObject *result = PyEval_CallObject(callback, args);
		Py_DECREF(args);
		if(result) Py_DECREF(result);
		PyGILState_Release(state);
    }
    virtual void onSplit(OTSplit *split) {
		PyGILState_STATE state = PyGILState_Ensure();
		PyObject *args = Py_BuildValue("({ss,si,si,si,si,si,si,si})",
			"ottype", "onSplit",
			"requestId", split->getRequestId(),
			"toFactor", split->getToFactor(),
			"forFactor", split->getForFactor(),
			"declarationDate", split->getDeclarationDate(),
			"executionDate", split->getExecutionDate(),
			"recordDate", split->getRecordDate(),
			"paymentDate", split->getPaymentDate()
			);
		PyObject *result = PyEval_CallObject(callback, args);
		Py_DECREF(args);
		if(result) Py_DECREF(result);
		PyGILState_Release(state);
	}
    virtual void onDividend(OTDividend *dividend) {
		PyGILState_STATE state = PyGILState_Ensure();
		PyObject *args = Py_BuildValue("({ss,si,sd,si,si,si,si,si,si,si,si,si,si,si,si,si})",
			"ottype", "onDividend",
			"requestId", dividend->getRequestId(),
			"price", dividend->getPrice(),
			"declarationDate", dividend->getDeclarationDate(),
			"executionDate", dividend->getExecutionDate(),
			"recordDate", dividend->getRecordDate(),
			"paymentDate", dividend->getPaymentDate(),
			"isApproximate", (int)dividend->isApproximate(),
       			"isAnnual", (int)dividend->isAnnual(),
       			"isCanadian", (int)dividend->isCanadian(),
       			"isExtra", (int)dividend->isExtra(),
			"isFinal", (int)dividend->isFinal(),
			"isIncrease", (int)dividend->isIncrease(),
       			"isSemiannual", (int)dividend->isSemiannual(),
			"isStock", (int)dividend->isStock(),
			"isSpecial", (int)dividend->isSpecial()
			);
		PyObject *result = PyEval_CallObject(callback, args);
		Py_DECREF(args);
		if(result) Py_DECREF(result);
		PyGILState_Release(state);
	}
    virtual void onOptionInit(OTOptionInit *optionInit) {
		PyGILState_STATE state = PyGILState_Ensure();
		PyObject *args = Py_BuildValue("({si,sc,sc,sd,si,sc,sc,sc,sc,sc,sc,sc})",
			"requestId", optionInit->getRequestId(),
			"underlyerSymbol", optionInit->getUnderlyerSymbol(),
			"symbol", optionInit->getSymbol(),
			"strikePrice", optionInit->getStrikePrice(),
			"contractSize", optionInit->getContractSize(),
			"expYear", optionInit->getExpYear(),
			"expMonth", optionInit->getExpMonth(),
			"expDay", optionInit->getExpDay(),
			"exerciseStyle", optionInit->getExerciseStyle(),
			"underlyerCusip", optionInit->getUnderlyerCusip(),
			"currency", optionInit->getCurrency(),
			"optionMarker", optionInit->getOptionMarker()
			);
		PyObject *result = PyEval_CallObject(callback, args);
		Py_DECREF(args);
		if(result) Py_DECREF(result);
		PyGILState_Release(state);
	}
};



//the global (and only permitted) OTClient 
TestClient client;

/******** wrappers for OTClient functions to be called from python ********/

static PyObject *
setCallback(PyObject *dummy, PyObject *args)
{
    PyObject *result = NULL;
    PyObject *obj;

    if (!PyArg_ParseTuple(args, "O:setCallback", &obj)) {
        PyErr_SetString(PyExc_TypeError, "error parsing parameters");
        return NULL;
	}
    if (!PyCallable_Check(obj)) {
        PyErr_SetString(PyExc_TypeError, "parameter must be callable");
        return NULL;
    }
    Py_XINCREF(obj);				/* Add a reference to new callback */
    Py_XDECREF(client.callback);	/* Dispose of previous callback */
    client.callback = obj;			/* Remember new callback */
    Py_INCREF(Py_None);				/* Boilerplate to return "None" */
    return Py_None;
}


static PyObject *
setDebug(PyObject *dummy, PyObject *args)
{
    PyObject *result = NULL;
    int num;

    if (!PyArg_ParseTuple(args, "i:setDebug", &num)) {
        PyErr_SetString(PyExc_TypeError, "error parsing parameters");
        return NULL;
	}
    client.debug=num;

    Py_INCREF(Py_None);				/* Boilerplate to return "None" */
    return Py_None;
}


static PyObject *
addHost(PyObject *self, PyObject *args) {
    LPCTSTR str ;
	int num;

	if (client.debug) {printf("addHost...");}
    if (!PyArg_ParseTuple(args,(char *)"si:addHost",&str, &num)) return NULL;
	client.addHost((char *)str, num);

    Py_INCREF(Py_None);
    return Py_None;
}


static PyObject *
clearHosts(PyObject *self, PyObject *args) {
    if (!PyArg_ParseTuple(args,(char *)":clearHosts")) return NULL;
	client.clearHosts();

    Py_INCREF(Py_None);
    return Py_None;
}


static PyObject *
login(PyObject *self, PyObject *args) {
    LPCTSTR str;
	LPCTSTR str2;

    if (!PyArg_ParseTuple(args,(char *)"ss:login",&str, &str2)) return NULL;
	client.login((char *)str, (char *)str2);

    Py_INCREF(Py_None);
    return Py_None;
}


static PyObject *
logout(PyObject *self, PyObject *args) {
    if (!PyArg_ParseTuple(args,(char *)":logout")) return NULL;
	client.logout();

    Py_INCREF(Py_None);
    return Py_None;
}


static PyObject *
isLoggedIn(PyObject *self, PyObject *args) {
	int result;

    if (!PyArg_ParseTuple(args,(char *)":isLoggedIn")) return NULL;
	result=client.isLoggedIn();
	return Py_BuildValue("i", result);
}


static PyObject *
getStatus(PyObject *self, PyObject *args) {
	int result;
	PyObject *obj;


    if (!PyArg_ParseTuple(args,(char *)":getStatus")) return NULL;
	result=client.getStatus();
	obj= Py_BuildValue("i", result);

	return obj;
}


static PyObject *
requestTickStream(PyObject *self, PyObject *args) {
    LPCTSTR str;
	LPCTSTR str2 ;
	int num, num2, result;

    if (!PyArg_ParseTuple(args,(char *)"(ss)ii:requestTickStream",&str, &str2, &num, &num2)) return NULL;
	result=client.requestTickStream(&OTDataEntity((char *)str, (char *)str2), num, num2);
	return Py_BuildValue("i", result);
}


static PyObject *
requestBookStream(PyObject *self, PyObject *args) {
    LPCTSTR str;
	LPCTSTR str2 ;
	int result;

    if (!PyArg_ParseTuple(args,(char *)"(ss):requestBookStream",&str, &str2)) return NULL;
	result=client.requestBookStream(&OTDataEntity((char *)str, (char *)str2));
	return Py_BuildValue("i", result);
}


static PyObject *
requestMarketDepth(PyObject *self, PyObject *args) {
    LPCTSTR str;
	LPCTSTR str2 ;
	int result;

    if (!PyArg_ParseTuple(args,(char *)"(ss):requestMarketDepth",&str, &str2)) return NULL;
	result=client.requestMarketDepth(&OTDataEntity((char *)str, (char *)str2));
	return Py_BuildValue("i", result);
}


static PyObject *
requestOptionChain(PyObject *self, PyObject *args) {
    LPCTSTR str;
	LPCTSTR str2 ;
	int result,num1,num2,num3,num4;

    if (!PyArg_ParseTuple(args,(char *)"(ss)iiii:requestOptionChain",&str, &str2, &num1, &num2, &num3, &num4)) return NULL;
	result=client.requestOptionChain(&OTDataEntity((char *)str, (char *)str2), num1, num2, num3, num4);
	return Py_BuildValue("i", result);
}


static PyObject *
requestEquityInit(PyObject *self, PyObject *args) {
    LPCTSTR str;
	LPCTSTR str2 ;
	int result;

    if (!PyArg_ParseTuple(args,(char *)"(ss):requestEquityInit",&str, &str2)) return NULL;
	result=client.requestEquityInit(&OTDataEntity((char *)str, (char *)str2));
	return Py_BuildValue("i", result);
}


static PyObject *
requestHistData(PyObject *self, PyObject *args) {
    LPCTSTR str;
	LPCTSTR str2 ;
	int result,num1,num2,num3,num4;

    if (!PyArg_ParseTuple(args,(char *)"(ss)iiii:requestHistData",&str, &str2, &num1, &num2, &num3, &num4)) return NULL;
	result=client.requestHistData(&OTDataEntity((char *)str, (char *)str2), num1, num2, num3, num4);
	return Py_BuildValue("i", result);
}


static PyObject *
requestHistTicks(PyObject *self, PyObject *args) {
    LPCTSTR str;
	LPCTSTR str2 ;
	int result,num1,num2,num3;

    if (!PyArg_ParseTuple(args,(char *)"(ss)iii:requestHistTicks",&str, &str2, &num1, &num2, &num3)) return NULL;
	result=client.requestHistTicks(&OTDataEntity((char *)str, (char *)str2), num1, num2, num3);
	return Py_BuildValue("i", result);
}


static PyObject *
requestTodaysOHL(PyObject *self, PyObject *args) {
    LPCTSTR str;
	LPCTSTR str2 ;
	int result;

    if (!PyArg_ParseTuple(args,(char *)"(ss):requestTodaysOHL",&str, &str2)) return NULL;
	result=client.requestTodaysOHL(&OTDataEntity((char *)str, (char *)str2));
	return Py_BuildValue("i", result);
}


static PyObject *
requestListExchanges(PyObject *self, PyObject *args) {
	int result;
	PyObject *obj;


    if (!PyArg_ParseTuple(args,(char *)":requestListExchanges")) return NULL;
	result=client.requestListExchanges();
	obj= Py_BuildValue("i", result);

	return obj;
}


static PyObject *
requestListSymbols(PyObject *self, PyObject *args) {
    LPCTSTR str ;
	int result;

    if (!PyArg_ParseTuple(args,(char *)"s:requestListSymbols",&str)) return NULL;
	result=client.requestListSymbols((char *)str);
	return Py_BuildValue("i", result);
}

static PyObject *
requestSplits(PyObject *self, PyObject *args) {
	LPCTSTR str;
	LPCTSTR str2 ;
	int num1, num2, result;
	if (!PyArg_ParseTuple(args,(char *)"(ss)ii:requestSplits",&str, &str2, &num1, &num2)) return NULL;
	result=client.requestSplits(&OTDataEntity((char *)str, (char *)str2), num1, num2);
	return Py_BuildValue("i", result);
}

static PyObject *
requestDividends(PyObject *self, PyObject *args) {
	LPCTSTR str;
	LPCTSTR str2;
	int num1, num2, result;
	if (!PyArg_ParseTuple(args,(char *)"(ss)ii:requestDividends",&str, &str2, &num1, &num2)) return NULL;
	result=client.requestDividends(&OTDataEntity((char *)str, (char *)str2), num1, num2);
	return Py_BuildValue("i", result);
}

static PyObject *
requestTickSnapshot(PyObject *self, PyObject *args) {
	LPCTSTR str;
	LPCTSTR str2;
	int num1, result;
	if (!PyArg_ParseTuple(args,(char *)"(ss)i:requestTickSnapshot",&str, &str2, &num1)) return NULL;
	result=client.requestTickSnapshot(&OTDataEntity((char *)str, (char *)str2), num1);
	return Py_BuildValue("i", result);
}

static PyObject *
requestOptionChainSnapshot(PyObject *self, PyObject *args) {
	LPCTSTR str;
	LPCTSTR str2;
	int num1, num5, result;
	short num2;
	double num3, num4;
	if (!PyArg_ParseTuple(args,(char *)"(ss)iiddi:requestOptionChainSnapshot",&str, &str2, &num1, &num2, &num3, &num4, &num5)) return NULL;
	result=client.requestOptionChainSnapshot(&OTDataEntity((char *)str, (char *)str2), num1, num2, num3, num4, num5);
	return Py_BuildValue("i", result);
}

static PyObject *
requestOptionInit(PyObject *self, PyObject *args) {
	LPCTSTR str;
	LPCTSTR str2;
	int result, num1, num2;
	if (!PyArg_ParseTuple(args,(char *)"(ss)ii:requestOptionInit", &str, &str2, &num1, &num2)) return NULL;
	result=client.requestOptionInit(&OTDataEntity((char *)str, (char *)str2), num1, num2);
	return Py_BuildValue("i", result);
}

static PyObject *
requestHistBooks(PyObject *self, PyObject *args) {
	LPCTSTR str;
	LPCTSTR str2;
	int result, num1, num2, num3;
	if (!PyArg_ParseTuple(args,(char *)"(ss)iii:requestHistBooks", &str, &str2, &num1, &num2, &num3)) return NULL;
	result=client.requestHistBooks(&OTDataEntity((char *)str, (char *)str2), num1, num2, num3);
	return Py_BuildValue("i", result);
}

static PyObject *
cancelTickStream(PyObject *self, PyObject *args) {
	int num;

    if (!PyArg_ParseTuple(args,(char *)"i:cancelTickStream",&num)) return NULL;
	client.cancelTickStream(num);
    Py_INCREF(Py_None);
    return Py_None;
}


static PyObject *
cancelOptionChain(PyObject *self, PyObject *args) {
	int num;

    if (!PyArg_ParseTuple(args,(char *)"i:cancelOptionChain",&num)) return NULL;
	client.cancelOptionChain(num);
    Py_INCREF(Py_None);
    return Py_None;
}


static PyObject *
cancelBookStream(PyObject *self, PyObject *args) {
	int num;

    if (!PyArg_ParseTuple(args,(char *)"i:cancelBookStream",&num)) return NULL;
	client.cancelBookStream(num);
    Py_INCREF(Py_None);
    return Py_None;
}


static PyObject *
cancelMarketDepth(PyObject *self, PyObject *args) {
	int num;

    if (!PyArg_ParseTuple(args,(char *)"i:cancelMarketDepth",&num)) return NULL;
	client.cancelMarketDepth(num);
    Py_INCREF(Py_None);
    return Py_None;
}


static PyObject *
cancelHistData(PyObject *self, PyObject *args) {
	int num;

    if (!PyArg_ParseTuple(args,(char *)"i:cancelHistData",&num)) return NULL;
	client.cancelHistData(num);
    Py_INCREF(Py_None);
    return Py_None;
}





static PyMethodDef methods[] = {
    {"setCallback", setCallback, METH_VARARGS,
     "sets the python callback function"},
    {"setDebug", setDebug, METH_VARARGS,
     "sets debug flag"},
    {"addHost", addHost, METH_VARARGS,
     "adds a host/port to the client host list"},
    {"clearHosts", clearHosts, METH_VARARGS,
     "to be added..."},
    {"login", login, METH_VARARGS,
     "to be added..."},
    {"logout", logout, METH_VARARGS,
     "to be added..."},
    {"isLoggedIn", isLoggedIn, METH_VARARGS,
     "to be added..."},
    {"getStatus", getStatus, METH_VARARGS,
     "to be added..."},
    {"requestTickStream", requestTickStream, METH_VARARGS,
     "to be added..."},
    {"requestBookStream", requestBookStream, METH_VARARGS,
     "to be added..."},
    {"requestMarketDepth", requestMarketDepth, METH_VARARGS,
     "to be added..."},
    {"requestOptionChain", requestOptionChain, METH_VARARGS,
     "to be added..."},
    {"requestEquityInit", requestEquityInit, METH_VARARGS,
     "to be added..."},
    {"requestHistData", requestHistData, METH_VARARGS,
     "to be added..."},
    {"requestHistTicks", requestHistTicks, METH_VARARGS,
     "to be added..."},
    {"requestTodaysOHL", requestTodaysOHL, METH_VARARGS,
     "to be added..."},
    {"requestListExchanges", requestListExchanges, METH_VARARGS,
     "to be added..."},
    {"requestListSymbols", requestListSymbols, METH_VARARGS,
     "to be added..."},
    {"requestSplits", requestSplits, METH_VARARGS,
     "to be added..."},
    {"requestDividends", requestDividends, METH_VARARGS,
     "to be added..."},
    {"requestTickSnapshot", requestTickSnapshot, METH_VARARGS,
     "to be added..."},
    {"requestOptionChainSnapshot", requestOptionChainSnapshot, METH_VARARGS,
     "to be added..."},
    {"requestOptionInit", requestOptionInit, METH_VARARGS,
     "to be added..."},
    {"requestHistBooks", requestHistBooks, METH_VARARGS,
     "to be added..."},
    {"cancelTickStream", cancelTickStream, METH_VARARGS,
     "cancels tick stream"},
    {"cancelOptionChain", cancelOptionChain, METH_VARARGS,
     "cancels option chain"},
    {"cancelBookStream", cancelBookStream, METH_VARARGS,
     "cancels book stream"},
    {"cancelMarketDepth", cancelMarketDepth, METH_VARARGS,
     "cancels market depth"},
    {"cancelHistData", cancelHistData, METH_VARARGS,
     "cancel historical data"},
    {NULL, NULL, 0, NULL}
};



void addConstant(PyObject *pDict, char *name, long num) {
	PyObject *obj;
	obj = PyInt_FromLong((long) num);
	PyDict_SetItemString(pDict, name, obj);
	Py_DECREF(obj);
}


void addConstants(char *moduleName) {
	// get the module dictionary
	PyObject *pName = PyString_FromString(moduleName);
    PyObject *pModule = PyImport_Import(pName);
    Py_DECREF(pName);
	PyObject *pDict = PyModule_GetDict(pModule);
	Py_DECREF(pModule);

	addConstant(pDict, "OT_STATUS_INACTIVE", OT_STATUS_INACTIVE);
	addConstant(pDict, "OT_STATUS_CONNECTING", OT_STATUS_CONNECTING);
	addConstant(pDict, "OT_STATUS_CONNECTED", OT_STATUS_CONNECTED);
	addConstant(pDict, "OT_STATUS_LOGGED_IN", OT_STATUS_LOGGED_IN);
	addConstant(pDict, "OT_MSG_END_OF_DATA", OT_MSG_END_OF_DATA);
	addConstant(pDict, "OT_MSG_END_OF_REQUEST", OT_MSG_END_OF_REQUEST);
	addConstant(pDict, "OT_INSTRUMENT_STOCK", OT_INSTRUMENT_STOCK);
	addConstant(pDict, "OT_INSTRUMENT_INDEX", OT_INSTRUMENT_INDEX);
	addConstant(pDict, "OT_INSTRUMENT_OPTION", OT_INSTRUMENT_OPTION);
	addConstant(pDict, "OT_INSTRUMENT_FUTURE", OT_INSTRUMENT_FUTURE);
	addConstant(pDict, "OT_HIST_RAW_TICKS", OT_HIST_RAW_TICKS);
	addConstant(pDict, "OT_HIST_OHLC_TICK_BASED", OT_HIST_OHLC_TICK_BASED);
	addConstant(pDict, "OT_HIST_OHLC_MINUTELY", OT_HIST_OHLC_MINUTELY);
	addConstant(pDict, "OT_HIST_OHLC_HOURLY", OT_HIST_OHLC_HOURLY);
	addConstant(pDict, "OT_HIST_OHLC_DAILY", OT_HIST_OHLC_DAILY);
	addConstant(pDict, "OT_HIST_OHLC_WEEKLY", OT_HIST_OHLC_WEEKLY);
	addConstant(pDict, "OT_HIST_OHLC_MONTHLY", OT_HIST_OHLC_MONTHLY);
	addConstant(pDict, "OT_HIST_OHLC_YEARLY", OT_HIST_OHLC_YEARLY);
	addConstant(pDict, "OT_ERR_OPENTICK", OT_ERR_OPENTICK);
	addConstant(pDict, "OT_ERR_SYSTEM", OT_ERR_SYSTEM);
	addConstant(pDict, "OT_ERR_SOCK", OT_ERR_SOCK);
	addConstant(pDict, "OT_ERR_INCORRECT_LOGIN", OT_ERR_INCORRECT_LOGIN);
	addConstant(pDict, "OT_ERR_NOT_LOGGED_IN", OT_ERR_NOT_LOGGED_IN);
	addConstant(pDict, "OT_ERR_NO_DATA", OT_ERR_NO_DATA);
	addConstant(pDict, "OT_ERR_INVALID_CANCEL_ID", OT_ERR_INVALID_CANCEL_ID);
	addConstant(pDict, "OT_ERR_INVALID_INTERVAL", OT_ERR_INVALID_INTERVAL);
	addConstant(pDict, "OT_ERR_NO_LICENSE", OT_ERR_NO_LICENSE);
	addConstant(pDict, "OT_ERR_LIMIT_EXCEEDED", OT_ERR_LIMIT_EXCEEDED);
	addConstant(pDict, "OT_ERR_DUPLICATE_REQUEST", OT_ERR_DUPLICATE_REQUEST);
	addConstant(pDict, "OT_ERR_INACTIVE_ACCOUNT", OT_ERR_INACTIVE_ACCOUNT);
	addConstant(pDict, "OT_ERR_LOGGED_IN", OT_ERR_LOGGED_IN);
	addConstant(pDict, "OT_ERR_BAD_REQUEST", OT_ERR_BAD_REQUEST);
	addConstant(pDict, "OT_ERR_NO_HIST_PACKAGE", OT_ERR_NO_HIST_PACKAGE);
	addConstant(pDict, "OT_ERR_NO_SOCKETS_DLL", OT_ERR_NO_SOCKETS_DLL);
	addConstant(pDict, "OT_ERR_SERVER_ERROR", OT_ERR_SERVER_ERROR);
	addConstant(pDict, "OT_ERR_CANNOT_CONNECT", OT_ERR_CANNOT_CONNECT);
	addConstant(pDict, "OT_ERR_BROKEN_CONNECTION", OT_ERR_BROKEN_CONNECTION);
	addConstant(pDict, "OT_ERR_NO_THREAD", OT_ERR_NO_THREAD);
	addConstant(pDict, "OT_ERR_NO_SOCKET", OT_ERR_NO_SOCKET);
	addConstant(pDict, "OT_TICK_TYPE_QUOTE", OT_TICK_TYPE_QUOTE);
	addConstant(pDict, "OT_TICK_TYPE_MMQUOTE", OT_TICK_TYPE_MMQUOTE);
	addConstant(pDict, "OT_TICK_TYPE_TRADE", OT_TICK_TYPE_TRADE);
	addConstant(pDict, "OT_TICK_TYPE_BBO", OT_TICK_TYPE_BBO);
	addConstant(pDict, "OT_TICK_TYPE_LEVEL1", OT_TICK_TYPE_LEVEL1);
	addConstant(pDict, "OT_TICK_TYPE_LEVEL2", OT_TICK_TYPE_LEVEL2);
	addConstant(pDict, "OT_TICK_TYPE_BOTH", OT_TICK_TYPE_BOTH);
	addConstant(pDict, "OT_TICK_TYPE_ALL", OT_TICK_TYPE_ALL);/** Book Cancel events */
	addConstant(pDict, "OT_BOOK_TYPE_CANCEL", OT_BOOK_TYPE_CANCEL);
	addConstant(pDict, "OT_BOOK_TYPE_CHANGE", OT_BOOK_TYPE_CHANGE);
	addConstant(pDict, "OT_BOOK_TYPE_DELETE", OT_BOOK_TYPE_DELETE);
	addConstant(pDict, "OT_BOOK_TYPE_EXECUTE", OT_BOOK_TYPE_EXECUTE);
	addConstant(pDict, "OT_BOOK_TYPE_ORDER", OT_BOOK_TYPE_ORDER);
	addConstant(pDict, "OT_BOOK_TYPE_PRICE_LEVEL", OT_BOOK_TYPE_PRICE_LEVEL);
	addConstant(pDict, "OT_BOOK_TYPE_PURGE", OT_BOOK_TYPE_PURGE);
	addConstant(pDict, "OT_BOOK_TYPE_REPLACE", OT_BOOK_TYPE_REPLACE);
	addConstant(pDict, "OT_BOOK_TYPE_ALL", OT_BOOK_TYPE_ALL);
}


PyMODINIT_FUNC
initopentick(void) {
	// initialize the python threading infrastructure
	PyEval_InitThreads( );

    // create the module and add the functions
    Py_InitModule("opentick", methods);
  
    //add the constants
	addConstants("opentick");

}

